package com.assic.utils.net;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;

import org.nutz.http.Header;
import org.nutz.http.Request;
import org.nutz.http.Request.METHOD;
import org.nutz.http.Response;
import org.nutz.lang.util.NutMap;

/**
 * Post请求发送器，解决URLReader读数据的时候参数长度太大的问题
 * 
 * @author 贵源<br>
 *         Create at 2014年3月5日
 */
public class URLPoster extends URLReader {

	private static int TIME_OUT = 5000;

	public void setTimeOut(int tIME_OUT) {
		TIME_OUT = tIME_OUT;
	}

	/**
	 * 
	 * 发送post请求
	 * 
	 * @param url
	 *            请求地址
	 * @param pEnv
	 *            发送编码
	 * @param rEnv
	 *            接受编码
	 * @param data
	 *            发送的数据的字节数组
	 * 
	 * @return 请求响应的内容
	 * @throws IOException
	 */
	public static String post(String url, String pEnv, String rEnv, byte[] data) throws IOException {
		String target = "";
		URL add = new URL(url);
		HttpURLConnection connection = (HttpURLConnection) add.openConnection();
		connection.setDoOutput(true);
		connection.setDoInput(true);
		connection.setUseCaches(false);
		connection.setRequestMethod("POST");
		connection.setRequestProperty("Charset", pEnv);
		connection.setConnectTimeout(TIME_OUT);

		connection.getOutputStream().write(data);
		connection.getOutputStream().flush();
		connection.getOutputStream().close();
		InputStream stream = connection.getInputStream();
		BufferedReader reader = new BufferedReader(new InputStreamReader(stream, rEnv));
		String temp = null;
		while ((temp = reader.readLine()) != null) {
			target += temp;
		}
		return target;
	}

	/**
	 * 文件下载
	 * 
	 * @param url
	 *            下载地址
	 * @param pEnv
	 *            下载编码
	 * @param rEnv
	 *            响应编码
	 * @param data
	 *            请求参数 字节数组
	 * @param fileName
	 *            文件名 相当于本地另存为文件名
	 * @return 文件对象
	 * @throws IOException
	 */
	public static File downLoad(String url, String pEnv, String rEnv, byte[] data, String fileName) throws IOException {
		// 创建临时文件用于接收
		File file = new File(fileName);
		// 打开url地址
		URL add = new URL(url);
		HttpURLConnection connection = (HttpURLConnection) add.openConnection();// 开启与url地址的链接
		connection.setDoOutput(true);// 设置长连接
		connection.setDoInput(true);
		connection.setUseCaches(false);// 设置非缓存 避免多次请求不能取到最新数据
		connection.setRequestMethod("POST");// 请求方式
		connection.setRequestProperty("Charset", pEnv);// 请求编码

		connection.getOutputStream().write(data);// 发送字节流的请求
		connection.getOutputStream().flush();// 清空字节流
		connection.getOutputStream().close();// 关闭请求流

		// 获取响应字节流
		InputStream stream = connection.getInputStream();

		// 文件输出流
		FileOutputStream fos = new FileOutputStream(file);
		// 流拷贝
		// 将流转换成reder
		BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
		// 创建文件写入writer
		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos));
		int i;
		while ((i = reader.read()) > 0) {
			writer.write(i);
		}
		writer.close();
		// 流关闭 //测试非关闭方式进行下载 流未关闭 不安全
		return file;
	}

	public static File downLoad(String url, byte[] data, String fileName) throws IOException {
		return downLoad(url, "UTF-8", "UTF-8", data, fileName);

		// List cars = (List)Info.get("cars");
	}

	/**
	 * 下载文件
	 * 
	 * @param url
	 * @param pInfo
	 * @param fileName
	 * @return
	 * @throws UnsupportedEncodingException
	 * @throws IOException
	 */
	public static File downLoad(String url, String pInfo, String fileName) throws UnsupportedEncodingException, IOException {
		return downLoad(url, pInfo.getBytes("UTF-8"), fileName);
	}

	/**
	 * 
	 * @param url
	 *            请求地址
	 * @param pEnv
	 *            发送编码
	 * @param rEnv
	 *            接收编码
	 * @param query
	 *            参数
	 * @return
	 * @throws IOException
	 */
	public static String post(String url, String pEnv, String rEnv, String query) throws IOException {
		return post(url, pEnv, rEnv, query.getBytes());
	}

	/**
	 * 
	 * @param url
	 *            请求地址
	 * @param pEnv
	 *            发送编码
	 * @param rEnv
	 *            接收编码
	 * @param paramMap
	 *            参数map
	 * @return
	 * @throws IOException
	 */
	public static String post(String url, String pEnv, String rEnv, Map paramMap) throws IOException {
		// 将参数map转换成字符串
		String query = parseMap(paramMap, pEnv);
		return post(url, pEnv, rEnv, query);
	}

	/**
	 * 解析参数map
	 * 
	 * @param paramMap
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private static String parseMap(Map paramMap, String pEnv) throws UnsupportedEncodingException {
		String target = "";
		Iterator ite = paramMap.keySet().iterator();
		while (ite.hasNext()) {
			String key = ite.next().toString();
			target += key + "=" + URLEncoder.encode(paramMap.get(key).toString(), pEnv) + "&";
		}
		return target.endsWith("&") ? target.substring(0, target.length() - 1) : target;
	}

	/**
	 * 以UTF-8发送post请求
	 * 
	 * @param url
	 * @param query
	 * @param rEnv
	 * @return
	 * @throws IOException
	 */
	public static String UTF8Post(String url, String query, String rEnv) throws IOException {
		return post(url, "UTF-8", rEnv, query);
	}

	/**
	 * 以UTF-8发送post请求
	 * 
	 * @param url
	 * @param rEnv
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
	public static String UTF8Post(String url, String rEnv, Map paramMap) throws IOException {
		return post(url, "UTF-8", rEnv, paramMap);
	}

	/**
	 * UTF8发送UTF8接受
	 * 
	 * @param url
	 * @param query
	 * @return
	 * @throws IOException
	 */
	public static String simpleUTF8Post(String url, String query) throws IOException {
		return UTF8Post(url, query, "UTF-8");
	}

	/**
	 * UTF8发送UTF8接受
	 * 
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
	public static String simpleUTF8Post(String url, Map paramMap) throws IOException {
		return UTF8Post(url, "UTF-8", paramMap);
	}

	/**
	 * 发送文件
	 * 
	 * @param url
	 * @param file
	 * @return
	 * @throws IOException
	 */
	public static String upload(String url, File file) throws IOException {
		String BOUNDARY = "---------KERBORES";
		String target = "";
		URL add = new URL(url);
		HttpURLConnection connection = (HttpURLConnection) add.openConnection();
		connection.setDoOutput(true);
		connection.setDoInput(true);
		connection.setUseCaches(false);
		connection.setRequestMethod("POST");
		connection.setRequestProperty("connection", "Keep-Alive");
		connection.setRequestProperty("Charset", "UTF-8");
		connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
		connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

		StringBuilder sb = new StringBuilder();

		sb.append("--");

		sb.append(BOUNDARY);

		sb.append("\r\n");

		sb.append("Content-Disposition: form-data;name=\"file\";filename=\"" + file.getName() + "\"\r\n");

		sb.append("Content-Type:application/octet-stream\r\n\r\n");

		byte[] data = sb.toString().getBytes();

		connection.getOutputStream().write(data);
		DataInputStream in = new DataInputStream(new FileInputStream(file));

		int bytes = 0;

		byte[] bufferOut = new byte[1024];

		while ((bytes = in.read(bufferOut)) != -1) {

			connection.getOutputStream().write(bufferOut, 0, bytes);

		}
		in.close();
		connection.getOutputStream().write("\r\n".getBytes());
		byte[] end_data = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
		connection.getOutputStream().write(end_data);

		connection.getOutputStream().flush();
		connection.getOutputStream().close();
		InputStream stream = connection.getInputStream();
		BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
		String temp = null;
		while ((temp = reader.readLine()) != null) {
			target += temp;
		}
		return target;
	}

	public static String upload(String url, File[] files) {

		return null;
	}

	/**
	 * 发送文件并传入数据
	 * 
	 * @param url
	 * @param file
	 * @param dataByte
	 * @return
	 * @throws IOException
	 */
	public static String upload(String url, File file, byte[] dataByte) throws IOException {
		String BOUNDARY = "---------KERBORES";
		String target = "";
		URL add = new URL(url);
		HttpURLConnection connection = (HttpURLConnection) add.openConnection();
		connection.setDoOutput(true);
		connection.setDoInput(true);
		connection.setUseCaches(false);
		connection.setRequestMethod("POST");
		connection.setRequestProperty("connection", "Keep-Alive");
		connection.setRequestProperty("Charset", "UTF-8");
		connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
		connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

		StringBuilder sb = new StringBuilder();

		sb.append("--");

		sb.append(BOUNDARY);

		sb.append("\r\n");

		sb.append("Content-Disposition: form-data;name=\"file\";filename=\"" + file.getName() + "\"\r\n");

		sb.append("Content-Type:application/octet-stream\r\n\r\n");

		byte[] data = sb.toString().getBytes();

		connection.getOutputStream().write(data);
		connection.getOutputStream().write(dataByte);
		connection.getOutputStream().write("\r\n".getBytes());
		DataInputStream in = new DataInputStream(new FileInputStream(file));

		int bytes = 0;

		byte[] bufferOut = new byte[1024];

		while ((bytes = in.read(bufferOut)) != -1) {

			connection.getOutputStream().write(bufferOut, 0, bytes);

		}
		in.close();
		connection.getOutputStream().write("\r\n".getBytes());
		byte[] end_data = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
		connection.getOutputStream().write(end_data);

		connection.getOutputStream().flush();
		connection.getOutputStream().close();
		InputStream stream = connection.getInputStream();
		BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
		String temp = null;
		while ((temp = reader.readLine()) != null) {
			target += temp;
		}
		return target;
	}

	/**
	 * 上传文件并发送参数
	 * 
	 * @param url
	 * @param file
	 * @param ps
	 * @return
	 * @throws IOException
	 */
	public static String upload(String url, File file, String ps) throws IOException {
		return upload(url, file, ps.getBytes("UTF-8"));
	}

	public static String upload(String url, File file, Map ps) throws IOException {
		String BOUNDARY = "---------KERBORES";
		String target = "";
		URL add = new URL(url);
		HttpURLConnection connection = (HttpURLConnection) add.openConnection();
		connection.setDoOutput(true);
		connection.setDoInput(true);
		connection.setUseCaches(false);
		connection.setRequestMethod("POST");
		connection.setRequestProperty("connection", "Keep-Alive");
		connection.setRequestProperty("Charset", "UTF-8");
		connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
		connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

		// 发送参数
		Iterator ite = ps.keySet().iterator();

		while (ite.hasNext()) {
			String key = ite.next().toString();
			String val = ps.get(key).toString();
			String dataInfo = BOUNDARY + "\r\n" + "Content-Disposition: form-data; name=\"" + key + "\"\r\n\r\n" + URLEncoder.encode(val, "UTF-8") + "\r\n" + BOUNDARY + "\r\n";
			connection.getOutputStream().write(dataInfo.getBytes("UTF-8"));
		}

		StringBuilder sb = new StringBuilder();

		sb.append("--");

		sb.append(BOUNDARY);

		sb.append("\r\n");

		sb.append("Content-Disposition: form-data;name=\"file\";filename=\"" + file.getName() + "\"\r\n");

		sb.append("Content-Type:application/octet-stream\r\n\r\n");

		byte[] data = sb.toString().getBytes();

		connection.getOutputStream().write(data);
		DataInputStream in = new DataInputStream(new FileInputStream(file));

		int bytes = 0;

		byte[] bufferOut = new byte[1024];

		while ((bytes = in.read(bufferOut)) != -1) {

			connection.getOutputStream().write(bufferOut, 0, bytes);

		}
		in.close();
		connection.getOutputStream().write("\r\n".getBytes());

		byte[] end_data = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
		connection.getOutputStream().write(end_data);

		connection.getOutputStream().flush();
		connection.getOutputStream().close();
		InputStream stream = connection.getInputStream();
		BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
		String temp = null;
		while ((temp = reader.readLine()) != null) {
			target += temp;
		}
		return target;
	}

	/**
	 * 上传一组文件并传递参数（模拟环境为 Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
	 * ）需要导入修改版的nut包 不然会导致nosuchMethodException
	 * 
	 * @param url
	 *            服务端地址
	 * @param files
	 *            待上传文件
	 * @param p
	 *            携带的其他参数map
	 * @return 服务器端响应字符串
	 * @throws IOException
	 */
	public static String upload(String url, File[] files, Map p) throws IOException {

		Map properties = new NutMap();// header信息
		properties.put("connection", "Keep-Alive");
		properties.put("Charset", "UTF-8");
		properties.put("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");

		Map params = new NutMap();// post参数
		params.put("file", files);
		Iterator iterator = p.keySet().iterator();// 处理文件之外的参数
		while (iterator.hasNext()) {
			Object key = iterator.next();
			params.put(key, p.get(key));
		}

		Header header = Header.create(properties);// 创建header

		Request request = Request.create(url, METHOD.POST, params, header);// 创建request对象

		IxionFileUploadPoster sender = new IxionFileUploadPoster(request);// sender
		Response response = sender.send();// 加强版post发送

		return response.getContent();
	}

}
